﻿#include "AVDumer.h"
#include "AAC_Decoder.h"
#include "Audio_Resampler.h"
#include <QDebug>
#define DEFAULT_AUDIO_SAMPLE 44100

AAC_Decoder::AAC_Decoder(AVContext* ac,QObject* parent)
    :QThread(parent)
    ,avContext_(ac)
{
    audioResampler_ = new Audio_Resampler();
}

int AAC_Decoder::Open(const AVCodecParameters* codecParamer)
{
    if(is_initial_ || !codecParamer)
    {
        return -1;
    }
    codec_ = const_cast<AVCodec*>(avcodec_find_decoder(codecParamer->codec_id));
    if (!codec_) {
        qDebug() << "audio avcodec_find_decoder failed.";
        return -1;
    }
    codecContext_ = avcodec_alloc_context3(codec_);
    if (avcodec_parameters_to_context(codecContext_, codecParamer) < 0) {
        qDebug() << "audio avcodec_parameters_to_context failed";
        return -1;
    }
    if(avcodec_open2(codecContext_, codec_, nullptr) != 0)
    {
        qDebug() << "avcodec_open2() failed.";
        return -1;
    }
    avContext_->audio_channels_layout = AV_CH_LAYOUT_STEREO;
    avContext_->audio_fmt = AV_SAMPLE_FMT_S16;
    avContext_->audio_sample_rate = DEFAULT_AUDIO_SAMPLE;
    if(!audioResampler_->Open(codecContext_->sample_rate,codecContext_->channels,codecContext_->sample_fmt,
                               DEFAULT_AUDIO_SAMPLE,2,AV_SAMPLE_FMT_S16))
    {
        qDebug() << "swr_context_ failed.";
        return -1;
    }
    avContext_->audio_dst_timebase = (AVRational){1,DEFAULT_AUDIO_SAMPLE};
    is_initial_ = true;
    start();
    return 0;
}

void AAC_Decoder::put_packet(const AVPacketPtr packet)
{
    audio_queue_.push(packet);
}

void AAC_Decoder::run()
{
    int ret = -1;
    AVPacketPtr pkt = nullptr;
    AVFramePtr outFrame = nullptr;
    AVFramePtr pFrame = AVFramePtr(av_frame_alloc(), [](AVFrame* p) {av_frame_free(&p);});
    while(!quit_ && audioResampler_)
    {
        if(!audio_queue_.size() || avContext_->audio_queue_.size() > 50)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(1));
            continue;
        }
        audio_queue_.pop(pkt);
        if (avcodec_send_packet(codecContext_, pkt.get())) {
            break;
        }
        while (true) {
            ret = avcodec_receive_frame(codecContext_, pFrame.get());
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF || ret < 0)
                break;
            else if(ret < 0)
            {
                return;
            }
            else
            {
                if(audioResampler_->Convert(pFrame,outFrame))
                {
                    if(outFrame)
                    {
                        avContext_->audio_queue_.push(outFrame);
                    }
                }
            }
        }
    }
}

void AAC_Decoder::Close()
{
    quit_ = true;
    if(isRunning())
    {
        this->quit();
        this->wait();
    }
    if(audioResampler_)
    {
        delete audioResampler_;
        audioResampler_ = nullptr;
    }
}

void AAC_Decoder::Clear()
{
    std::lock_guard<std::mutex> lock(mutex_);
    avcodec_flush_buffers(codecContext_);
    audio_queue_.clear();
}

AAC_Decoder::~AAC_Decoder()
{
    Close();
}

